﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;

namespace ProjectFootball.Foundation.Interfaces
{
    public static class _IApprovableEntity
    {
        public static TEntityV GetApprovedVersion<THeader, TEntityV>(this THeader header, DateTime viewDate)
            where THeader : IHeaderEntity<TEntityV>
            where TEntityV : IApprovableEntity
        {
            return header.Versions.Single(t => t.EffectiveFrom <= viewDate && t.EffectiveTo >= viewDate && t.IsApproved);
        }

        public static IEnumerable<TEntityV> GetApprovedVersions<THeader, TEntityV>(this IEnumerable<THeader> headers, DateTime viewDate)
            where THeader : IHeaderEntity<TEntityV>
            where TEntityV : IApprovableEntity
        {
            foreach (var header in headers)
            { 
                if (header.Versions.Any(t => t.EffectiveFrom <= viewDate && t.EffectiveTo >= viewDate && t.IsApproved))
                    yield return header.Versions.Single(t => t.EffectiveFrom <= viewDate && t.EffectiveTo >= viewDate && t.IsApproved);
            }
        }

        public static IEnumerable<TEntityV> GetApprovedVersions<TEntityV>(this ICollection<TEntityV> entityVs, DateTime viewDate)
            where TEntityV : IApprovableEntity
        {
            return entityVs.Where(e => e.IsApproved && !e.IsMarkedForDeletion && e.EffectiveFrom <= viewDate && e.EffectiveTo >= viewDate);
        }

        public static IEnumerable<TEntityV> GetApprovedVersions<TEntityV>(this IEnumerable<TEntityV> entityVs, DateTime viewDate)
            where TEntityV : IApprovableEntity
        {
            return entityVs.Where(e => e.IsApproved && !e.IsMarkedForDeletion && e.EffectiveFrom <= viewDate && e.EffectiveTo >= viewDate);
        }

        public static bool CanView(this IApprovableEntity entity, Guid userId, bool isAdmin)
        {
            if ((entity.IsPublic && entity.IsApproved) || entity.IsOwner(userId))
                return true;

            if (entity.CanApprove(isAdmin))
                return true;

            return false;
        }

        public static bool CanEdit(this IApprovableEntity entity, IPrincipal user)
        {
            return user.GetUserId() == entity.OwnerUserId || user.IsAdmin();
        }

        public static bool CanApprove(this IApprovableEntity entity, bool isAdmin)
        {
            return !entity.IsApproved && isAdmin;
        }

        public static bool IsOwner(this IApprovableEntity entity, Guid userId)
        {
            return entity.OwnerUserId == userId;
        }

        public static TViewModel ToViewModel<TViewModel, TEntityV>(this TEntityV entityV, DateTime viewDate)
            where TViewModel : IApprovableViewModel<TEntityV>, new()
            where TEntityV : IApprovableEntity
        {
            return new TViewModel()
            {
                PrimaryKey = entityV.PrimaryKey,
                ViewDate = viewDate,
                HeaderKey = entityV.HeaderKey,
                EffectiveFrom = entityV.EffectiveFrom,
                EffectiveTo = entityV.EffectiveTo,
                VersionEntity = entityV
            };
        }
    }
}
